(display "\n========================================\n")
(define (enumerate-interval low high)
    (if (> low high)
        '()
        (cons low (enumerate-interval (+ low 1) high))))
; (display (enumerate-interval 1 5))
; (newline)

(define (accmulate op initial seq)
    (if (null? seq)
        initial
        (op (car seq)
            (accmulate op initial (cdr seq)))))

(define (flatmap proc seq)
    (accmulate append '() (map proc seq)))

(define empty-board '())

(define (adjoin-position new-row k rest-of-queens)
    (cons new-row rest-of-queens))

(define (safe? k position)
    (iter-check (car position) (cdr position) 1))

(define (iter-check row-of-new-queen rest-of-queens i)
    (if (null? rest-of-queens)
        #t
        (let ((row-of-current-queen (car rest-of-queens)))
            (if (or (= row-of-new-queen row-of-current-queen)
                    (= row-of-new-queen (+ row-of-current-queen i))
                    (= row-of-new-queen (- row-of-current-queen i)))
                #f
                (iter-check row-of-new-queen (cdr rest-of-queens) (+ i 1))))))

(define (queens board-size)
    (define (queen-cols k)
        (if (= k 0)
            (list empty-board)
            (filter (lambda (positions) (safe? k positions))
                    (flatmap (lambda (rest-of-queens)
                                     (map (lambda (new-row)
                                                  (adjoin-position new-row k rest-of-queens))
                                          (enumerate-interval 1 board-size)))
                             (queen-cols (- k 1))))))
    (queen-cols board-size))

; (display (queens 8))
; (newline)

(for-each (lambda (pos)
                  (begin
                        (display pos)
                        (newline)))
                  (queens 8))

(display "\n========================================\n")